/**
 * Created by ${PRODUCT_NAME}.
 * User: skylerparr
 * Date: 12/23/10
 * Time: 6:40 AM
 * To change this template use File | Settings | File Templates.
 */
package com.thoughtorigin.meta {
import com.thoughtorigin.reflect.FunctionMetaDataItem;
import com.thoughtorigin.reflect.MetaArg;
import com.thoughtorigin.reflect.MetaDataItem;
import com.thoughtorigin.relay.MessageRelay;

import flash.display.DisplayObject;
import flash.display.DisplayObject;
import flash.events.Event;
import flash.utils.Dictionary;

public class HandlerMetaData implements MetaType {

    private var _messageRelay: MessageRelay;
    private var _eventName: String;
    private var _function: Function;
    private static var _decorationDictionay: Dictionary;

    public function HandlerMetaData() {
        if(!_decorationDictionay) {
            _decorationDictionay = new Dictionary(true);
        }
    }

    public function decorate(object:Object, metadata:MetaDataItem, callback:Function):void {
        if(_decorationDictionay[object + _eventName]) {
            if(callback != null) {
                callback.call(this);
            }
            return;
        }
        _eventName = MetaArg(metadata.metaArgs[0]).value;
        _function = object[FunctionMetaDataItem(metadata).functionName];
        _messageRelay.addEventListener(_eventName, _function);
        if(object is DisplayObject) {
            DisplayObject(object).addEventListener(Event.REMOVED_FROM_STAGE, dispose);
        }
        if(object is ViewComponent) {
            ViewComponent(object).view.addEventListener(Event.REMOVED_FROM_STAGE, dispose);
        }
        _decorationDictionay[object + _eventName] = new HandlerStorage(_eventName, _function);
        if(callback != null) {
            callback.call(this);
        }
    }

    public function preprocess(clazz:Class, metadata:MetaDataItem):void {
    }

    public function dispose(... args):void {
        var e: Event = args[0];
        var displayObject: DisplayObject = DisplayObject(e.target);
        var store: HandlerStorage = _decorationDictionay[displayObject + _eventName];
        displayObject.removeEventListener(Event.REMOVED_FROM_STAGE, dispose);
        if(!store) {
            return;
        }
        _messageRelay.removeEventListener(store._eventName, store._function);
        delete _decorationDictionay[displayObject];
    }

    public function get priority():int {
        return 5;
    }

    [Inject]
    public function set messageRelay(value : MessageRelay): void {
        _messageRelay = value;
    }
}
}

class HandlerStorage {
    public var _eventName: String;
    public var _function: Function;
    public function HandlerStorage(eventName: String, func: Function) {
        _eventName = eventName;
        _function = func;
    }
}